package com.dingreading.cloud.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 腾讯地图工具类
 */
public class TencentMapUtil {
    //叮叮 18158855766
    public static final String KEY = "XO4BZ-X5WKD-INT4H-PWUYY-MD3KO-VMBUX";
    //小雨象
//    public static final String KEY = "VR2BZ-G4VYF-MFIJU-NT6UM-DAEFT-JRBOG";
    private static final Logger logger = LoggerFactory.getLogger(TencentMapUtil.class);

//    public static void main(String[] args) {
//        Map<String, String> stringMap = getLongitudeAndLatitude("安徽省合肥市庐阳区界首路缤纷南国绮霞居10栋102室叮叮书房");
//        System.out.println("stringMap = " + stringMap);
//    }

    /**
     * 根据地址获取经纬度
     *
     * @param address 地址
     * @return map longitude:经度，latitude：纬度
     */
    public static Map<String, String> getLongitudeAndLatitude(String address) {
        Map<String, String> result = new HashMap<>(2);
        try {
            String longitude = "";
            String latitude = "";

            // 签名计算
            String path = "/ws/geocoder/v1?address=%s&key=%s";
            path = String.format(path, address, KEY);
            String sig = MD5Util.MD5Encode(path + "MeSBQ30NKRx4Q4z8DTpqxrrq07uim2yY");
            String url = "https://apis.map.qq.com" + path + "&sig=" + sig;

//            String url = "https://apis.map.qq.com/ws/geocoder/v1/?address=%s&key=%s";
//            url = String.format(url, address, KEY, sig);

//            System.out.println("url = " + url);
            JSONObject returnObj = JSON.parseObject(HttpUtils.get(url));
            int status = returnObj.getIntValue("status");
            //查询成功
            if (status == 0) {
                String resultStr = returnObj.getString("result");
                JSONObject resultObject = JSON.parseObject(resultStr);
                String locationStr = resultObject.getString("location");
                JSONObject locationObject = JSON.parseObject(locationStr);
                longitude = locationObject.getString("lng");
                latitude = locationObject.getString("lat");
            } else {
                System.out.println("腾讯地图查询失败");
                System.out.println(status);
                System.out.println(returnObj);
            }
            result.put("longitude", longitude);
            result.put("latitude", latitude);
        } catch (Exception e) {
            logger.error(ExceptionLogs.getErrorInfoFromException(e));
        }
        return result;
    }

    /**
     * 根据经纬度获取所在区划
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @return map 坐标集合
     */
    public static JSONArray getPolygonList(String longitude, String latitude) {
        JSONArray result = new JSONArray();
        try {
            //获取adCode
            JSONObject coderLocation = getCoderLocation(longitude, latitude);
            String adCode = coderLocation.getJSONObject("result").getJSONObject("ad_info").getString("adcode");

            String url = "https://apis.map.qq.com/ws/district/v1/search?get_polygon=2&keyword=%s&key=%s";
            url = String.format(url, adCode, KEY);
            JSONObject returnObj = JSON.parseObject(HttpUtils.get(url));
            int status = returnObj.getIntValue("status");
            //查询成功
            if (status == 0) {
                JSONObject secondResult = returnObj.getJSONArray("result").getJSONArray(0).getJSONObject(0);
                JSONArray polygon = secondResult.getJSONArray("polygon").getJSONArray(0);
                JSONObject object;
                for (int i = 1; i < polygon.size() - 1; i++) {
                    if (i % 2 == 1) {
                        object = new JSONObject();
                        object.put("longitude", polygon.get(i - 1));
                        object.put("latitude", polygon.get(i));
                        result.add(object);
                    }
                }
            } else {
                System.out.println("腾讯地图查询失败");
                System.out.println(status);
                System.out.println(returnObj);
            }
        } catch (Exception e) {
            logger.error(ExceptionLogs.getErrorInfoFromException(e));
        }
        return result;
    }

    /**
     * 逆地址解析（坐标位置描述)
     *
     * @param latitude  纬度
     * @param longitude 经度
     * @return json
     */
    public static JSONObject getCoderLocation(String longitude, String latitude) {
        JSONObject result = new JSONObject();
        try {
            String url = "https://apis.map.qq.com/ws/geocoder/v1/?location=%s,%s&key=%s";
            url = String.format(url, latitude, longitude, KEY);
            result = JSON.parseObject(HttpUtils.get(url));
            int status = result.getIntValue("status");
            //查询成功
            if (status == 0) {

            } else {
                System.out.println("腾讯地图查询失败");
                System.out.println(status);
                System.out.println(result);
            }
        } catch (Exception e) {
            logger.error(ExceptionLogs.getErrorInfoFromException(e));
        }
        return result;
    }

    /**
     * 获取1.5公里内的经度和纬度
     *
     * @return latitudeMin、latitudeMax、longitudeMin、longitudeMax
     */
    public static Map<String, Double> getFourPoint(
            String longitude, String latitude
    ) {
        HashMap<String, Double> map = new HashMap<>(16);
        try {
            //纬度每差一度就是111公里
            double s = 1.5 / 111;
            double latitudeMax = Double.parseDouble(latitude) + s;
            double latitudeMin = Double.parseDouble(latitude) - s;
            map.put("latitudeMax", latitudeMax);
            map.put("latitudeMin", latitudeMin);
            //赤道上经度每差一度才是111公里，其他地方要乘以纬度的cos
            double l = 1.5 / (111 * Math.cos(Double.parseDouble(latitude) * Math.PI / 180));
            double longitudeMax = Double.parseDouble(longitude) + l;
            double longitudeMin = Double.parseDouble(longitude) - l;
            map.put("longitudeMax", longitudeMax);
            map.put("longitudeMin", longitudeMin);
        } catch (Exception e) {
            logger.error(ExceptionLogs.getErrorInfoFromException(e));
        }
        return map;
    }

    /**
     * 获取xx公里内的经度和纬度
     *
     * @return latitudeMin、latitudeMax、longitudeMin、longitudeMax
     */
    public static Map<String, Double> getFourPoint(
            String longitude, String latitude, Double kilometers
    ) {
        HashMap<String, Double> map = new HashMap<>(16);
        try {
            //纬度每差一度就是111公里
            double s = kilometers / 111;
            double latitudeMax = Double.parseDouble(latitude) + s;
            double latitudeMin = Double.parseDouble(latitude) - s;
            map.put("latitudeMax", latitudeMax);
            map.put("latitudeMin", latitudeMin);
            //赤道上经度每差一度才是111公里，其他地方要乘以纬度的cos
            double l = kilometers / (111 * Math.cos(Double.parseDouble(latitude) * Math.PI / 180));
            double longitudeMax = Double.parseDouble(longitude) + l;
            double longitudeMin = Double.parseDouble(longitude) - l;
            map.put("longitudeMax", longitudeMax);
            map.put("longitudeMin", longitudeMin);
        } catch (Exception e) {
            logger.error(ExceptionLogs.getErrorInfoFromException(e));
        }
        return map;
    }

    public static double getDistance(double latBegin, double lngBegin, double latEnd, double lngEnd) {

        double EARTH_RADIUS = 6378.137;

        double radLatBegin = latBegin * Math.PI / 180.0;
        double radLatEnd = latEnd * Math.PI / 180.0;
        double radLatDiff = radLatBegin - radLatEnd;
        double radLngDiff = lngBegin * Math.PI / 180.0 - lngEnd * Math.PI / 180.0;

        double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(radLatDiff / 2), 2) +
                Math.cos(radLatBegin) * Math.cos(radLatEnd) * Math.pow(Math.sin(radLngDiff / 2), 2)));
        return distance * EARTH_RADIUS;
    }

    /**
     * 计算两个经纬间的距离/公里
     */
    public static double algorithm(String longitude1, String latitude1, String longitude2, String latitude2) {

        double lat1 = rad(Double.parseDouble(latitude1));
        // 纬度
        double lat2 = rad(Double.parseDouble(latitude2));
        //两点纬度之差
        double a = lat1 - lat2;
        //经度之差
        double b = rad(Double.parseDouble(longitude1)) - rad(Double.parseDouble(longitude2));
        //计算两点距离的公式
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(b / 2), 2)));
        //弧长乘地球半径（半径为米）
        s = s * 6378137.0;
        //精确距离的数值
        s = Math.round(s * 10000d) / 10000d;
        return s;
    }

    private static double rad(double d) {
        //角度转换成弧度
        return d * Math.PI / 180.00;
    }
}
